
#ifndef CHORDMSG_H_

#define CHORDMSG_H_

#include "common.h"
#include "packet.h"

class ChordKeyInfo;

class ChordMsg : public Packet{
	public:
		enum MSG_TYPE{
			SEARCH_MSG,
			SEARCH_RESP_MSG,
			NOTIFY_MSG,
			GET_MSG,
			GET_RESP_MSG,
			TRANSFER_KEY_MSG,
			TRANSFER_KEY_RESP_MSG
		};
		enum TARGET_TYPE{
			TARGET_SUCCESSOR = 0,
			TARGET_PREDCESSOR
		};
		enum RESP_CODE{
			CODE_ILLEGAL = 0,
			CODE_FORWARD,
			CODE_HIT,
			CODE_MISS
		};
		static uint32_t msg_id_counter;

		static const uint32_t chord_msg_header_len = 8;

		static const int16_t code_illegal = -1;
		static const int16_t code_forward = 0;
		static const int16_t code_hit = 1;
		static const int16_t code_miss = 2;

		ChordMsg( chord_net_id_t net_id, MSG_TYPE t, node_id_t s_id, uint16_t len )
			: Packet(s_id, len, Packet::CHORD_PACKET)
			, net_id_(net_id)
			, type_(t)
			, msg_id_(msg_id_counter++)
		{}
		virtual ~ChordMsg() {}

		chord_net_id_t getChordNetID() const {return net_id_;}
		MSG_TYPE       getType() const { return type_; }
		uint32_t       getMsgID() const { return msg_id_; }
	protected:
		chord_net_id_t net_id_;
		MSG_TYPE type_;
		uint32_t msg_id_;
};

class ChordSearchMsg : public ChordMsg{
	public:
		ChordSearchMsg( chord_key_t k, TARGET_TYPE target, chord_net_id_t net_id, node_id_t s_id )
			: ChordMsg( net_id, SEARCH_MSG, s_id, packet_header_len+chord_msg_header_len+6 )
			, key_(k) 
			, target_(target)
   			, data_(false)	{}
			bool successor() { return TARGET_SUCCESSOR==target_; }
			bool predecessor() { return TARGET_PREDCESSOR==target_; }
	protected:
		chord_key_t key_;
		TARGET_TYPE target_;
		bool		data_;

	    friend class ChordNode;
		friend class ChordProtocol;
};

//search response message
class ChordSearchRespMsg : public ChordMsg{
	public:
		ChordSearchRespMsg( chord_key_t k, chord_net_id_t net_id, node_id_t s_id ) 
			: ChordMsg( net_id, SEARCH_RESP_MSG, s_id, packet_header_len+chord_msg_header_len+14 )
			, key_(k)
			, code_(CODE_ILLEGAL){}

		void setForward( node_id_t id ){
			code_ = CODE_FORWARD;
			info_.node_id_ = id;
		}
		void setHit( node_id_t n_id, chord_node_id_t c_nid ) {
			code_ = CODE_HIT;
			info_.node_id_   = n_id;
			info_.chord_nid_ = c_nid;
		}
		void setMiss(){
			code_ = CODE_MISS;
		}

		node_id_t getForwardNodeID() const { return info_.node_id_; }

	protected:
		chord_key_t key_;
		RESP_CODE code_;
		ChordNodeInfo info_;

	    friend class ChordNode;
		friend class ChordProtocol;
};

class ChordNotifyMsg : public ChordMsg{
	public:
		ChordNotifyMsg( chord_node_id_t c_nid, node_id_t n_id, chord_net_id_t net_id )
			: ChordMsg( net_id, NOTIFY_MSG, n_id, packet_header_len+chord_msg_header_len+8 )
		{
			info_.node_id_ = n_id;
			info_.chord_nid_ = c_nid;
		}
	protected:
		ChordNodeInfo info_;

	    friend class ChordNode;
		friend class ChordProtocol;
};

class ChordGetMsg : public ChordMsg{
	public: 
		ChordGetMsg( TARGET_TYPE target, chord_net_id_t net_id, node_id_t s_id )
			: ChordMsg( net_id, GET_MSG, s_id, packet_header_len+chord_msg_header_len+1 )	
			, target_( target )
		{}
	protected:
		TARGET_TYPE target_;

	    friend class ChordNode;
		friend class ChordProtocol;

};

class ChordGetRespMsg : public ChordMsg{
	public:
		ChordGetRespMsg( chord_net_id_t net_id, node_id_t s_id )
			: ChordMsg( net_id, GET_RESP_MSG, s_id, packet_header_len+chord_msg_header_len+8 ){
			}
	protected:
		ChordNodeInfo info_;

	    friend class ChordNode;
		friend class ChordProtocol;
};

class ChordTransferKeyMsg : public ChordMsg{
	public:
		ChordTransferKeyMsg( ChordKeyInfo *key_info, chord_net_id_t net_id, node_id_t s_id )
			: ChordMsg( net_id, TRANSFER_KEY_MSG, s_id, packet_header_len+chord_msg_header_len+chord_data_len )
			, key_info_( key_info )
		{}
	protected:
		ChordKeyInfo *key_info_;

};

class ChordTransferKeyRespMsg : public ChordMsg{
	public:
		ChordTransferKeyRespMsg( ChordKeyInfo *key_info, chord_net_id_t net_id, node_id_t s_id )
			: ChordMsg( net_id, TRANSFER_KEY_MSG, s_id, packet_header_len+chord_msg_header_len+chord_data_len )
			, key_info_( key_info )
		{}
	protected:
		ChordKeyInfo *key_info_;

};

#endif /* CHORDMSG_H_ */

